/*
 * Copyright  2018 Linkel Technology Co., Ltd, Beijing
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BA SIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import {
    showNotification,
    GET_ONE,
    fetchStart,
    fetchEnd,
    crudCreate,
    SaveButton,
    Toolbar
} from 'react-admin';
import indexDataProvider from '../../dataprovider/ra-data-indexdb';
import settings from '../../settings';
// import buildGraphQLProvider from '../../adaptator';
import { RestAPI, Transaction, Crypto } from 'rclink';
import _ from "lodash";
import { push } from 'react-router-redux';

//Transaction加载protobuf定义
// Transaction.setTxMsgType().then(data => {
//     console.log('setTxMsgType:' + data);
// }).catch(e => {
//     console.error("setTxMsgType err:\n", e);
// })

const saveToCreate = (data, basePath, redirectTo) => {
    return crudCreate('Transaction', data, basePath, redirectTo);
}

class SignSubmitButtonView extends Component {
    constructor() {
        super();
        //this.handleClick = this.handleClick.bind(this);
        this.state = { dataProvider: null };
    }

    componentDidMount() {
        // let me = this;
        // buildGraphQLProvider({
        //     clientOptions: { uri: settings.Prisma.endpoint }
        // }).then(dataProvider => {
        //     me.dataProvider = dataProvider;
        // });
    }

    componentWillUnmount() {
        window.removeEventListener("message", this.receiveMessage, false);
    }

    handleClick = () => {
        const {
            handleSubmit,
            basePath,
            redirect,
            saveToCreate,
            showNotification,
            fetchStart,
            fetchEnd,
            push,
        } = this.props;

        return handleSubmit(async record => {
            fetchStart();
            let { prvKP, pubKP, certName } = await indexDataProvider(GET_ONE, 'keypairs', { id: record.account.keypairID })
                .then((data) => {
                    return { prvKP: data.data.kp.prvKeyPEM, pubKP: data.data.kp.pubKeyPEM, certName: data.data.name };
                })
                .catch(e => {
                    showNotification('' + e, 'warning')
                    fetchEnd();
                });
            try {
                const transactionConsArgs = _.cloneDeep(record);
                let itype = record.type;
                switch (itype) {
                    case "CHAINCODE_DEPLOY":
                        transactionConsArgs.chaincodeDeployParams.timeout = 1000;
                        break;
                    case "CHAINCODE_INVOKE":
                        transactionConsArgs.chaincodeInvokeParams.chaincodeFunctionArgs
                            = transactionConsArgs.chaincodeInvokeParams.chaincodeFunctionArgs
                                .map(value => value.arg);
                        break;
                    case "CHAINCODE_SET_STATE":
                        transactionConsArgs.chaincodeSetStateParams.state
                            = transactionConsArgs.chaincodeSetStateParams.state === "true"
                                ? true
                                : false;
                        break;
                    default:
                        break;
                }
                let t = new Transaction(transactionConsArgs);
                let txSignedBuffer = t.sign({
                    prvKey: prvKP,
                    pubKey: pubKP,
                    alg: "ecdsa-with-SHA1",
                    pass: record.keypairPwd,
                    creditCode: record.account.creditCode,
                    certName,
                });

                let rest = new RestAPI(settings.RepChain.default.url_api);
                await rest.sendTransaction(txSignedBuffer)
                    .then(r => {
                        if (r.err) throw r.err;
                        showNotification('resources.Transaction.notification.send_success',
                            'info', { messageArgs: { txId: r.txid } });
                        console.log('TX send feedback:\n', JSON.stringify(r));
                    })
                    .catch(e => { throw e })
                    .finally(fetchEnd);

                // save record
                // const transactionRecord = _.cloneDeep(record);
                // transactionRecord.txid = t.getTxMsg().id;
                // transactionRecord.chaincodeID = {connect: {
                //     fieldsHash: Crypto.GetHashVal({data: `${record.chaincodeName}-${record.chaincodeVersion}`})
                // }};
                // transactionRecord.chaincodeInvokeParams = { connect: {
                //     fieldsHash: Crypto.GetHashVal({data: `${record.chaincodeInvokeParams.chaincodeFunction}-${record.chaincodeFunctionArgs}`})
                // }};
                // transactionRecord.signature = {create: {
                //     timestamp: new Date(t.getTxMsg().signature.tmLocal.seconds * 1000 - 8 * 3600 * 1000),
                //     signature: t.getTxMsg().signature.signature.toString('hex'),
                //     certID: {connect: {
                //         fieldsHash: Crypto.GetHashVal({data: `${t.getTxMsg().signature.certId.creditCode}-${t.getTxMsg().signature.certId.certName}`})
                //     }}
                // }};
                // transactionRecord.timestamp = transactionRecord.signature.create.timestamp; 
                push(redirect);
                return;
                // 目前保存交易到prisma不成功，可能需要更改并简化prisma datamodel
                // return saveToCreate(transactionRecord, basePath, redirect);
            } catch (e) {
                showNotification('' + e, 'warning');
                return;
            }
        });
    }

    render() {
        const { handleSubmitWithRedirect, ...props } = this.props;

        return (
            <SaveButton
                handleSubmitWithRedirect={this.handleClick}
                id="submitTransaction"
                {...props}
            />
        );
    }
}

SignSubmitButtonView.propTypes = {
    fetchStart: PropTypes.func,
    fetchEnd: PropTypes.func,
    showNotification: PropTypes.func,
    saveToCreate: PropTypes.func,
    basePath: PropTypes.string,
    redirect: PropTypes.string
};

const SignSubmitButton = connect(undefined, {
    showNotification,
    fetchStart,
    fetchEnd,
    saveToCreate,
    push,
})(SignSubmitButtonView);

const CreateToolbar = props => (
    <Toolbar {...props}>
        <SignSubmitButton
            label='resources.Transaction.button.sign_submit'
            redirect='/Transaction'
            submitOnEnter={false}
            variant='raised'
        />
    </Toolbar>
)

export default CreateToolbar;